// RedJey Graphics User Interface Library for J2ME Platform.
// Copyright (C) 2008 Yevgen Krapiva
//
// This library is free software; you can redistribute
// it and/or modify it under the terms of the
// GNU Lesser General Public License as published
// by the Free Software Foundation; either version 3.0
// of the License, or any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//

package com.incrediblesoft.redjey;

/**
 * @author Yevgen Krapiva<br>
 *         Homepage: http://code.google.com/p/redjey/<br>
 *         Feedback: ykrapiva@gmail.com<br>
 *         Copyright (C) 2008 Yevgen Krapiva<br>
 */

import com.incrediblesoft.redjey.backgrounds.AbstractBackground;
import com.incrediblesoft.redjey.borders.AbstractBorder;

import javax.microedition.lcdui.Graphics;
import java.util.Hashtable;
import java.util.Enumeration;

public class Style
{
    //AbstractBackground part
    AbstractBackground background;
    //AbstractBorder part
    AbstractBorder border;
    //Font
    CustomFont font;
    //Component inner offsets
    int paddingLeft;
    int paddingTop;
    int paddingRight;
    int paddingBottom;
    //Offsets between some inner parts in component
    int paddingVertical;
    int paddingHorizontal;
    //Component outside offsets
    int marginLeft;
    int marginTop;
    int marginRight;
    int marginBottom;
    //Additional attributes
    Hashtable attributes;


    /**
     * Creates a new Style.
     *
     * @param marginLeft the margin in pixels to the next element on the left
     * @param marginRight the margin in pixels to the next element on the right
     * @param marginTop the margin in pixels to the next element on the top
     * @param marginBottom the margin in pixels to the next element on the bottom
     * @param paddingLeft the padding between the left border and content in pixels
     * @param paddingRight the padding between the right border and content in pixels
     * @param paddingTop the padding between the top border and content in pixels
     * @param paddingBottom the padding between the bottom border and content in pixels
     * @param paddingVertical the vertical padding between internal elements of an item
     * @param paddingHorizontal the horizontal padding between internal elements of an item
     * @param font the content-font for this style
     * @param background the background for this style
     * @param border the border for this style
     * @param attributes additional attributes
     */
    public Style( int marginLeft, int marginRight, int marginTop, int marginBottom,
                  int paddingLeft, int paddingRight, int paddingTop, int paddingBottom, int paddingHorizontal, int paddingVertical,
                  CustomFont font, AbstractBackground background, AbstractBorder border, Hashtable attributes
                )
    {
        this.marginLeft = marginLeft;
        this.marginRight = marginRight;
        this.marginTop = marginTop;
        this.marginBottom = marginBottom;
        this.paddingLeft = paddingLeft;
        this.paddingRight = paddingRight;
        this.paddingTop = paddingTop;
        this.paddingBottom = paddingBottom;
        this.paddingVertical = paddingVertical;
        this.paddingHorizontal = paddingHorizontal;
        this.font = font;
        this.background = background;
        this.border = border;
        this.attributes = attributes == null ? new Hashtable() : attributes;
    }

    public Style(CustomFont font, AbstractBackground background, AbstractBorder border, Hashtable attributes)
    {
        this(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, font, background, border, attributes);
    }

    public Style()
    {
        this(null, null, null, null);
    }

    public int getMinWidth()
    {
        return getLeftInset() + getRightInset();
        //return marginLeft + marginRight + (border != null? border.getMinWidth() : 0) + paddingLeft + paddingRight + (background != null? background.borderWidth * 2 : 0);
    }

    public int getMinHeight()
    {
        return getTopInset() + getBottomInset();
        //return marginTop + marginBottom + (border != null? border.getMinHeight() : 0) + paddingTop + paddingBottom + (background != null? background.borderHeight * 2 : 0);
    }

    public int getLeftInset()
    {
        return marginLeft + (border != null? border.getLeftBorderWidth() : 0) + paddingLeft + (background != null? background.borderWidth : 0);
    }

    public int getTopInset()
    {
        return marginTop + (border != null? border.getTopBorderWidth() : 0) + paddingTop + (background != null? background.borderHeight : 0);
    }

    public int getRightInset()
    {
        return marginRight + (border != null? border.getRightBorderWidth() : 0) + paddingRight + (background != null? background.borderWidth : 0);
    }

    public int getBottomInset()
    {
        return marginBottom + (border != null? border.getBottomBorderWidth() : 0) + paddingBottom + (background != null? background.borderHeight : 0);
    }

    public void setFont(CustomFont font)
    {
        this.font = font;
    }

    public CustomFont getFont()
    {
        return font;
    }

    public void setBorder(AbstractBorder border)
    {
        this.border = border;
    }

    public void setBackground(AbstractBackground background)
    {
        this.background = background;
    }

    public int getPaddingLeft()
    {
        return paddingLeft;
    }

    public void setPaddingLeft(int paddingLeft)
    {
        this.paddingLeft = paddingLeft;
    }

    public int getPaddingTop()
    {
        return paddingTop;
    }

    public void setPaddingTop(int paddingTop)
    {
        this.paddingTop = paddingTop;
    }

    public int getPaddingRight()
    {
        return paddingRight;
    }

    public void setPaddingRight(int paddingRight)
    {
        this.paddingRight = paddingRight;
    }

    public int getPaddingBottom()
    {
        return paddingBottom;
    }

    public void setPaddingBottom(int paddingBottom)
    {
        this.paddingBottom = paddingBottom;
    }

    public int getPaddingVertical()
    {
        return paddingVertical;
    }

    public void setPaddingVertical(int paddingVertical)
    {
        this.paddingVertical = paddingVertical;
    }

    public int getPaddingHorizontal()
    {
        return paddingHorizontal;
    }

    public void setPaddingHorizontal(int paddingHorizontal)
    {
        this.paddingHorizontal = paddingHorizontal;
    }

    public int getMarginLeft()
    {
        return marginLeft;
    }

    public void setMarginLeft(int marginLeft)
    {
        this.marginLeft = marginLeft;
    }

    public int getMarginTop()
    {
        return marginTop;
    }

    public void setMarginTop(int marginTop)
    {
        this.marginTop = marginTop;
    }

    public int getMarginRight()
    {
        return marginRight;
    }

    public void setMarginRight(int marginRight)
    {
        this.marginRight = marginRight;
    }

    public int getMarginBottom()
    {
        return marginBottom;
    }

    public void setMarginBottom(int marginBottom)
    {
        this.marginBottom = marginBottom;
    }

    public Hashtable getAttributes()
    {
        return attributes;
    }

    public void setAttributes(Hashtable attributes)
    {
        this.attributes = attributes;
    }

    public void addAttribute(Object key, Object value)
    {
        attributes.put(key, value);
    }

    public void tick(int dt)
    {
        if (border != null)
            border.tick(dt);
        if (background != null)
            background.tick(dt);
    }

    public void paint(Graphics g, int x, int y, int width, int height)
    {
        x += marginLeft;
        y += marginTop;
        width -= (marginLeft + marginRight);
        height -= (marginTop + marginBottom);

        if (background != null)
            background.paint(g, x, y, width, height);
        
        if (border != null)
        {
            border.paint(g, x, y, width, height);
            x += border.getLeftBorderWidth();
            y += border.getTopBorderWidth();
            width -= border.getLeftBorderWidth() + border.getRightBorderWidth();
            height -= border.getTopBorderWidth() + border.getBottomBorderWidth();
        }
    }

    /**
     * Clones this style. Each component must have a local copy of template's style.
     * Note: this method doesn't clone hashtable attributes because of fact that
     * Object component in CLDC doesn't have clone method.
     * @return cloned style
     */
    public Style clone()
    {
        Hashtable newAttributes = new Hashtable();
        Enumeration keys = attributes.keys();

        while(keys.hasMoreElements())
        {
            Object key = keys.nextElement();
            Object value = attributes.get(key);
            newAttributes.put(key, value);
        }

        AbstractBackground newBackground = background != null ? background.clone() : null;
        AbstractBorder newBorder = border != null ? border.clone() : null;
        CustomFont newFont = font != null ? font.clone() : null;

        Style newStyle = new Style(marginLeft, marginRight, marginTop, marginBottom, paddingLeft, paddingRight, paddingTop, paddingBottom, paddingHorizontal, paddingVertical, newFont, newBackground, newBorder, newAttributes);
        return newStyle;
    }

}
